#ifndef _INTERCODE_H
#define _INTERCODE_H

#include "common.h"

typedef struct Operand_* Operand;
typedef struct InterCode_* InterCode;
typedef struct Label_No_* Label_No;

typedef struct Operand_{
	enum{   TEMPVAR,VARIABLE,CONSTANT,ADDRESS,LABEL,FUNCTION_ }kind;
    union{
        bool valid;//for labels
        bool isRight;//for tempvar
    };
	union{
		int var_no;
		char* value;//usually a name
	};
	Operand next;
} Operand_;

typedef struct InterCode_{
    enum {
        IR_LABEL,   // LABEL result :
        IR_FUNC,    // FUNCTION result :
        IR_ASSIGN,  // result := arg1
        IR_ADD,     // result := arg1 + arg2
        IR_SUB,     // result := arg1 - arg2
        IR_MUL,     // result := arg1 * arg2
        IR_DIV,     // result := arg1 / arg2

        IR_ADDR,    // result  := &arg1
        IR_DEREF_R, // result  := *arg1, dereference at right :-)
        IR_DEREF_L, // *result :=  arg1, dereference at left :-)

        IR_GOTO,    // GOTO result
        IR_IFGOTO,   // IF arg1 [relop] arg2 GOTO result
        IR_RETURN,  // RETURN result
        IR_DEC,     // DEC result [size]
        IR_ARG,     // ARG result
        IR_CALL,    // result := CALL arg1
        IR_PARAM,   // PARAM result

        IR_READ,    // READ result
        IR_WRITE    // WRITE result
    } kind;

	union{
		struct{	Operand op;	}sinop;
		struct{ Operand left,right; }assign;
		struct{ Operand op1,op2,result; }binop;
		struct{ Operand x; Operand y; Operand label; char *op; }triop;
		struct{ Operand op; int size; }dec;
	};

	InterCode pre;
	InterCode next;
} InterCode_;

void insertCode(InterCode c);
void deleteCode(InterCode c);
void printCode(char *fileName);
void printOp(Operand p,FILE *fp);

extern InterCode code_head,code_tail;
extern int temVarNo;
extern int labelNo;
extern int varNo;

void optimizeGoto();
void deleteLabel();
void computeConst();

#endif
